//
// Created by ycl on 2024/11/6.
//

#include "project_glob.h"

#include "project_inner_init.h"

ProjectParam param;


/*
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 * 放前面的函数 START
 *
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */


/**
 * 系统时钟配置函数
 */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // 初始化外部高速时钟 (HSE)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    // 初始化系统时钟
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
        RCC_CLOCKTYPE_SYSCLK |
        RCC_CLOCKTYPE_PCLK1 |
        RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    {
        Error_Handler();
    }
}


/**
 * 初始化单个GPIO
 * @param gpio
 * @param pin
 * @param mode
 * @param pull
 * @param speed
 */
void projectInitGpioOne(GPIO_TypeDef* gpio,
                        uint16_t pin,
                        uint8_t mode,
                        uint8_t pull,
                        uint8_t speed)
{
    GPIO_InitTypeDef gpio_init;
    gpio_init.Pin = pin;
    gpio_init.Mode = mode;
    gpio_init.Pull = pull;
    gpio_init.Speed = speed;
    HAL_GPIO_Init(gpio, &gpio_init);
}


/**
 * TIM实际初始化函数
 * @param htim              参数
 * @param tim               TIM_TypeDef指针
 * @param counterMode       计数模式
 * @param clockDivision     时钟分割
 * @param prescaler         分频
 * @param period            周期
 * @param autoReload        自动重载
 */
void initTim(TIM_HandleTypeDef* htim,
             TIM_TypeDef* tim,
             uint32_t counterMode, // 计数模式
             uint32_t clockDivision, // 时钟分割
             uint32_t prescaler, // 分频
             uint32_t period, // 周期
             uint32_t autoReload // 是否自动重载
)
{
    htim->Instance = tim;
    htim->Init.Prescaler = prescaler;
    htim->Init.CounterMode = counterMode;
    htim->Init.Period = period;
    htim->Init.ClockDivision = clockDivision;
    htim->Init.AutoReloadPreload = autoReload;
    if (HAL_TIM_Base_Init(htim) != HAL_OK)
    {
        Error_Handler();
    }

    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(htim, &sClockSourceConfig) != HAL_OK)
    {
        Error_Handler();
    }

    TIM_MasterConfigTypeDef sMasterConfig = {0};
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(htim, &sMasterConfig) != HAL_OK)
    {
        Error_Handler();
    }

    //清理中断标识
    __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
    //使能TIM中断
    HAL_TIM_Base_Start_IT(htim);
}


/**
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 * 放前面的函数 END
 *
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */

/**
 * 工程全局初始化函数
 */
void projectInit(void)
{
    SystemInit();
    setProjectFlag(&PROJECT_System_METHOD_EXCUTE_FLAG, 63, true);

    HAL_Init();
    setProjectFlag(&PROJECT_System_METHOD_EXCUTE_FLAG, 62, true);

    projectInitClock();
    setProjectFlag(&PROJECT_CUSTOM_METHOD_EXCUTE_FLAG, 62, true);

    projectInitGpio();
    setProjectFlag(&PROJECT_CUSTOM_METHOD_EXCUTE_FLAG, 61, true);

    projectInitTim();
    setProjectFlag(&PROJECT_CUSTOM_METHOD_EXCUTE_FLAG, 60, true);


    //该函数执行完毕
    setProjectFlag(&PROJECT_CUSTOM_METHOD_EXCUTE_FLAG, 63, true);
}


/**
 * 设置工程全局标志位
 * @param projectFlag 标志
 * @param p 位置
 * @param v 当前标志位的值
 */
void setProjectFlag(uint64_t* projectFlag, uint8_t p, bool v)
{
    if (p < 0 || p > 63)
    {
        PROJECT_ERR("project_glob.h: setProjectFlag: p is out of range");
        return;
    }
    uint64_t i = 1 << p;
    if (v)
        *projectFlag |= i;
    else
        *projectFlag &= ~i;
}


/**
 * 获取工程全局标志位
 * @param projectFlag 标志
 * @param p 位置
 * @return bool 当前标志位的值
 */
bool getProjectFlag(uint64_t* projectFlag, uint8_t p)
{
    if (p < 0 || p > 63)
    {
        //报错
        PROJECT_ERR("project_glob.h: getProjectFlag: p is out of range");
        return false;
    }
    return (*projectFlag & (1 << p)) != 0;
}


/**
 * 初始化所有时钟
 */
void projectInitClock(void)
{
    SystemClock_Config();
    __HAL_RCC_AFIO_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_USART2_CLK_ENABLE();
    __HAL_RCC_USART3_CLK_ENABLE();

    __HAL_RCC_SYSCFG_CLK_ENABLE();

    __HAL_RCC_PWR_CLK_ENABLE();

    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_TIM2_CLK_ENABLE();
    __HAL_RCC_TIM3_CLK_ENABLE();
    __HAL_RCC_TIM4_CLK_ENABLE();
}


/**
 * 初始化TIM
 */
void projectInitTim(void)
{
    // 每秒 1 次中断
    initTim(&param.htim1, TIM1, TIM_COUNTERMODE_UP, TIM_CLOCKDIVISION_DIV1, 72000 - 1, 1000 - 1,
            TIM_AUTORELOAD_PRELOAD_DISABLE);
    initTim(&param.htim2, TIM2, TIM_COUNTERMODE_UP, TIM_CLOCKDIVISION_DIV1, 72000 - 1, 1000 - 1,
            TIM_AUTORELOAD_PRELOAD_DISABLE);
    initTim(&param.htim3, TIM3, TIM_COUNTERMODE_UP, TIM_CLOCKDIVISION_DIV1, 72000 - 1, 1000 - 1,
            TIM_AUTORELOAD_PRELOAD_DISABLE);
    initTim(&param.htim4, TIM4, TIM_COUNTERMODE_UP, TIM_CLOCKDIVISION_DIV1, 72000 - 1, 1000 - 1,
            TIM_AUTORELOAD_PRELOAD_DISABLE);
}


/**
 * 初始化所有GPIO
 */
void projectInitGpio(void)
{
    projectInitGpioOne(GPIOC, GPIO_PIN_13, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW);
    projectInitGpioOne(GPIOC, GPIO_PIN_14, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW);
    projectInitGpioOne(GPIOC, GPIO_PIN_15, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW);

    projectInitGpioOne(GPIOA, GPIO_PIN_0, GPIO_MODE_AF_PP,GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);
}

/**
 * TIM2中断服务函数 (HAL库提供)
 */
void TIM2_IRQHandler(void)
{
    // ProjectParam param;
    HAL_TIM_IRQHandler(&param.htim2);
}

/**
 * 初始化TIM2的中断服务函数 (HAL库提供)
 * @param htim
 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim)
{
    if (htim->Instance == TIM2)
    {
        HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
        //清理中断标识
        __HAL_TIM_CLEAR_FLAG(htim, TIM_SR_UIF);
        //使能TIM中断
        HAL_TIM_Base_Start_IT(htim);
    }
}

/**
 * HAL库发现错误时会自动调用
 */
void Error_Handler(void)
{
    while (1);
}
